﻿using Microsoft.Rest;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Text;

namespace XSot.BitBrowser.LocalApiClient
{
    public partial class BitBrowserLocalApiClient : ServiceClient<BitBrowserLocalApiClient>, IBitBrowserLocalApiClient
    {

        /// <summary>
        /// Gets json serialization settings.
        /// </summary>
        public static JsonSerializerSettings JsonSerializationSettings { get; }

        static BitBrowserLocalApiClient()
        {
            JsonSerializationSettings = new()
            {
                Formatting = Formatting.None,
                DateTimeZoneHandling = DateTimeZoneHandling.Utc,
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Ignore,
                ContractResolver = new CamelCasePropertyNamesContractResolver()
                {
                    NamingStrategy = new CamelCaseNamingStrategy()
                },
                Converters = new List<JsonConverter>()
                {
                    new StringEnumConverter(new CamelCaseNamingStrategy())
                }
            };
        }

        /// <summary>
        /// The base URI of the service.
        /// </summary>
        public Uri BaseUri { get; } = new Uri("http://127.0.0.1:54345");
        /// <summary>
        /// 
        /// </summary>
        public string ApiKey { get; set; } = string.Empty;
        /// <summary>
        /// 使用默认的http://127.0.0.1:54345创建客户端
        /// </summary>
        public BitBrowserLocalApiClient()
            : this(new Uri("http://127.0.0.1:54345"), new HttpClientHandler())
        {
        }
        /// <summary>
        /// 使用默认的http://127.0.0.1:54345创建客户端
        /// </summary>
        /// <param name="handler"></param>
        public BitBrowserLocalApiClient(HttpClientHandler handler)
            : this(new Uri("http://127.0.0.1:54345"), handler)
        {
        }
        /// <summary>
        /// 使用指定的<paramref name="baseUri"/>和<paramref name="handler"/>创建客户端
        /// </summary>
        /// <param name="baseUri"></param>
        /// <param name="handler"></param>
        public BitBrowserLocalApiClient(Uri baseUri, HttpClientHandler handler)
            : base(handler)
        {
            BaseUri = baseUri;
        }


        private Task<HttpResult<T>> GetResponseAsync<T>(string relativeUrl, object payload)
        {
            payload ??= new object();
            var req = new HttpRequestMessage(HttpMethod.Post, new Uri(BaseUri, relativeUrl))
            {
                Content = new StringContent(JsonConvert.SerializeObject(payload, JsonSerializationSettings), Encoding.UTF8, "application/json")
            };

            if (!string.IsNullOrEmpty(ApiKey))
            {
                req.Headers.TryAddWithoutValidation("x-api-key", ApiKey);
            }

            return HttpClient.SendAsync(req)
                .ContinueWith(t =>
                {
                    var hr = new HttpResult<T>()
                    {
                        Request = req,
                        Response = t.Result,
                        Error = t.Exception
                    };

                    if (hr.Response != null)
                    {
                        hr.ResponseText = hr.Response.Content.ReadAsStringAsync().Result;

                        var jo = JObject.Parse(hr.ResponseText);

                        hr.Success = jo.Value<bool>("success");
                        hr.Message = jo.Value<string>("msg");

                        if (hr.Success)
                        {
                            if (jo.TryGetValue("data", out var jt))
                            {
                                try
                                {
                                    var serializer = JsonSerializer.Create(JsonSerializationSettings);
                                    hr.Body = jt.ToObject<T>(serializer)!;
                                }
                                catch (Exception ex)
                                {
                                    hr.Message = ex.Message;
                                    hr.Success = false;
                                    hr.Error = ex;
                                }
                            }
                        }
                    }

                    return hr;
                });
        }
    }
}